import 'dart:convert';
import 'dart:io';
import 'package:audioplayers/audioplayers.dart';
import 'package:bot_toast/bot_toast.dart';
import 'package:decimal/decimal.dart';
import 'package:device_info_plus/device_info_plus.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_image_compress/flutter_image_compress.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:intl/intl.dart';
import 'package:logger/logger.dart';
import 'package:pdfx/pdfx.dart';
import 'package:shared_preferences/shared_preferences.dart';

int seconds = 2;
bool clickClose = false;
bool onlyOne = true;
bool crossPage = true;

double align = 0.8;
int fontSize = 17;
int borderRadius = 8;
int fontColor = 0xFFFFFFFF;
int backgroundColor = 0x00000000;
int contentColor = 0x8A000000;
int animationMilliseconds = 200;
int animationReverseMilliseconds = 200;

int index = 0;

class Utils {
  static File? file;
  static Uint8List? byteData;
  static AudioCache audioCache = AudioCache();
  static AudioPlayer audioPlayer = AudioPlayer();
  static String? user;
  // static final pdaPrinterFlutter3Plugin = PdaPrinterFlutter3();
  static var logger = Logger(
    printer: PrettyPrinter(),
  );
  static DeviceInfoPlugin deviceInfo = DeviceInfoPlugin();

  /// 设备信息对象初始化
  static Future<String> getAndroidModelInfo() async {
    try {
      AndroidDeviceInfo androidInfo = await deviceInfo.androidInfo;
      return androidInfo.model;
    } on Exception {
      return 'Failed to get device infomation.';
    }
  }

  /// 获取应用缓存
  static SharedPreferences? prefs;

  int numXiaoShouChuku = 0;

  /// 缓存对象初始化
  static void initSP() async {
    prefs = await SharedPreferences.getInstance();
  }

  /// 缓存写入（int）方法
  static Future<bool> setIntIntoSP(String key, int value) async {
    return await prefs?.setInt(key, value) ?? false;
  }

  /// 缓存写入（bool）方法
  static Future<bool> setBoolIntoSP(String key, bool value) async {
    return await prefs?.setBool(key, value) ?? false;
  }

  /// 缓存写入（double）方法
  static Future<bool> setDoubleIntoSP(String key, double value) async {
    return await prefs?.setDouble(key, value) ?? false;
  }

  /// 缓存写入（String）方法
  static Future<bool> setStringIntoSP(String key, String value) async {
    return await prefs?.setString(key, value) ?? false;
  }

  /// 缓存写入（List<String>）方法
  static Future<bool> setStringListIntoSP(String key, List<String> list) async {
    return await prefs?.setStringList(key, list) ?? false;
  }

  /// 缓存读取（Int）方法
  static int? getIntFromSP(String key) {
    return prefs?.getInt(key);
  }

  /// 缓存读取（Bool）方法
  static bool? getBoolFromSP(String key) {
    return prefs?.getBool(key);
  }

  /// 缓存读取（double）方法
  static double? getDoubleFromSP(String key) {
    return prefs?.getDouble(key);
  }

  /// 缓存读取（String）方法
  static String? getStringFromSP(String key) {
    return prefs?.getString(key);
  }

  /// 缓存读取（List<String>）方法
  static List<String>? getStringListFromSP(String key) {
    return prefs?.getStringList(key);
  }

  /// 播放报错提示音
  static playLocalMp3() async {
    await audioPlayer.play(AssetSource('sounds/error.mp3'));
  }

  /// 提示消息
  static void showToast(String msg) {
    BotToast.showText(
      text: msg,
      duration: Duration(seconds: seconds),
      onlyOne: onlyOne,
      clickClose: clickClose,
      crossPage: crossPage,
      align: Alignment(0, align),
      animationDuration: Duration(milliseconds: animationMilliseconds),
      animationReverseDuration:
          Duration(milliseconds: animationReverseMilliseconds),
      textStyle:
          TextStyle(color: Color(fontColor), fontSize: fontSize.toDouble()),
      borderRadius: BorderRadius.circular(borderRadius.toDouble()),
      backgroundColor: Color(backgroundColor),
      contentColor: Color(contentColor),
    );
  }

  /// 显示对话框（只有确定按钮）
  static void showMyDialog(BuildContext context, String title, String content,
      VoidCallback callback) {
    String myTitle = title.isNotEmpty ? title : '温馨提示';
    showDialog(
      context: context,
      barrierDismissible: false,
      builder: (context) {
        // ignore: deprecated_member_use
        return WillPopScope(
          onWillPop: () async {
            Utils.showToast("禁止使用系统回退键");
            return false;
          },
          child: AlertDialog(
            title: Text(
              myTitle,
              style: const TextStyle(
                color: Colors.black54,
                fontSize: 18.0,
              ),
            ),
            content: SingleChildScrollView(
              child: Text(content),
            ),
            actions: <Widget>[
              TextButton(
                  onPressed: () {
                    callback();
                  },
                  child: const Text('确定')),
            ],
          ),
        );
      },
    );
  }

  // static void showMyDialogNew(BuildContext context, String title,
  //     String content, PopInvokedCallback callback) async {
  //   String mytitle = title.isNotEmpty ? title : '温馨提示';
  //   // ignore: unused_result
  //   final result = await showOkAlertDialog(
  //     context: context,
  //     title: mytitle,
  //     message: content,
  //     onPopInvoked: callback,
  //   );
  //   logger.i(result);
  // }

  /// 展示数据集合提示框（只有确定按钮）
  static void showMyListDataDialog(BuildContext context, String title,
      List<String> contents, VoidCallback callback) {
    String mytTitle = title.isNotEmpty ? title : '温馨提示';
    showDialog(
      context: context,
      builder: (
        context,
      ) {
        // ignore: deprecated_member_use
        return WillPopScope(
          onWillPop: () async {
            Utils.showToast("禁止使用系统回退键");
            return false;
          },
          child: AlertDialog(
            title: Text(
              mytTitle,
              style: const TextStyle(
                color: Colors.black54,
                fontSize: 18.0,
              ),
            ),
            content: SingleChildScrollView(
                child: SizedBox(
              width: ScreenUtil().setWidth(520),
              height: ScreenUtil().setHeight(600),
              child: CustomScrollView(
                shrinkWrap: true,
                slivers: <Widget>[
                  SliverFixedExtentList(
                    itemExtent: ScreenUtil().setHeight(160),
                    delegate: SliverChildBuilderDelegate(
                      (BuildContext context, int index) {
                        return Container(
                          alignment: Alignment.center,
                          color: Colors.white70,
                          child: Column(
                            children: <Widget>[
                              Row(
                                children: <Widget>[
                                  Container(
                                    width: ScreenUtil().setWidth(460),
                                    height: ScreenUtil().setHeight(160),
                                    alignment: Alignment.center,
                                    child: Text(
                                        contents.isNotEmpty
                                            ? contents[index]
                                            : '',
                                        softWrap: true),
                                  ),
                                ],
                              ),
                            ],
                          ),
                        );
                      },
                      childCount: contents.isNotEmpty ? contents.length : 0,
                    ),
                  ),
                ],
              ),
            )),
            actions: <Widget>[
              TextButton(
                  onPressed: () {
                    callback();
                  },
                  child: const Text('确定')),
            ],
          ),
        );
      },
    );
  }

  /// 显示对话框（有取消、确定按钮）
  static void showMyConfirmDialog(
      BuildContext context,
      String title,
      String content,
      VoidCallback confirmCallback,
      VoidCallback cancelCallback) {
    String myTitle = title.isNotEmpty ? title : '温馨提示';
    showDialog(
      context: context,
      barrierDismissible: false,
      builder: (context) {
        // ignore: deprecated_member_use
        return WillPopScope(
          onWillPop: () async {
            Utils.showToast("禁止使用系统回退键");
            return false;
          },
          child: AlertDialog(
            title: Text(
              myTitle,
              style: const TextStyle(
                color: Colors.black54,
                fontSize: 18.0,
              ),
            ),
            content: SingleChildScrollView(
              child: Text(content),
            ),
            actions: <Widget>[
              TextButton(
                  onPressed: () {
                    cancelCallback();
                  },
                  child: const Text('取消')),
              TextButton(
                  onPressed: () {
                    confirmCallback();
                  },
                  child: const Text('确定')),
            ],
          ),
        );
      },
    );
  }

  static const Duration _timeout = Duration(seconds: 1);

  static void startTimeOut(int milliseconds, VoidCallback callback) {
    // ignore: unnecessary_null_comparison
    var duration =
        // ignore: unnecessary_null_comparison
        milliseconds == null ? _timeout : Duration(microseconds: milliseconds);
    Future.delayed(duration, callback);
  }

  /// 显示输入对话框（有取消、确定按钮）
  static void showMyInputDialog(
      BuildContext context,
      String title,
      String content,
      String lable,
      String unit,
      TextEditingController controller,
      VoidCallback cancelCallback,
      VoidCallback confirmCallback) {
    String myTitle = title.isNotEmpty ? title : '温馨提示';
    showDialog(
      context: context,
      barrierDismissible: false,
      builder: (context) {
        // ignore: deprecated_member_use
        return WillPopScope(
          onWillPop: () async {
            Utils.showToast("禁止使用系统回退键");
            return false;
          },
          child: AlertDialog(
            title: Text(
              myTitle,
              style: const TextStyle(
                color: Colors.black54,
                fontSize: 18.0,
              ),
            ),
            content: Container(
              height: ScreenUtil().setWidth(150),
              alignment: Alignment.centerLeft,
              child: Column(
                children: <Widget>[
                  Visibility(
                    visible: content.isNotEmpty,
                    child: Row(
                      children: <Widget>[
                        Text(content),
                      ],
                    ),
                  ),
                  Row(
                    children: [
                      Visibility(
                        visible: lable.isNotEmpty,
                        child: Padding(
                          padding: EdgeInsets.only(
                            left: ScreenUtil().setWidth(10),
                            right: ScreenUtil().setWidth(10),
                          ),
                          child: Text(lable),
                        ),
                      ),
                      Expanded(
                        child: Container(
                          height: ScreenUtil().setHeight(60),
                          alignment: Alignment.center,
                          child: TextField(
                            keyboardType: TextInputType.number,
                            autofocus: true,
                            controller: controller,
                            decoration: InputDecoration(
                              filled: true,
                              fillColor: Colors.white,
                              labelStyle: const TextStyle(
                                color: Colors.pink,
                                fontSize: 18,
                              ),
                              contentPadding: EdgeInsets.only(
                                  left: ScreenUtil().setWidth(10)),
                              hintText: lable.isNotEmpty ? '输入$lable' : '扫码HU',
                              border: const OutlineInputBorder(
                                borderSide: BorderSide(
                                  color: Colors.pink,
                                ),
                              ),
                            ),
                          ),
                        ),
                      ),
                      Visibility(
                        visible: unit.isNotEmpty,
                        child: Padding(
                          padding: EdgeInsets.only(
                            left: ScreenUtil().setWidth(10),
                            right: ScreenUtil().setWidth(10),
                          ),
                          child: Text(unit),
                        ),
                      ),
                    ],
                  )
                ],
              ),
            ),
            actions: <Widget>[
              TextButton(
                  onPressed: () {
                    cancelCallback();
                  },
                  child: const Text('取消')),
              TextButton(
                  onPressed: () {
                    confirmCallback();
                  },
                  child: const Text('确定')),
            ],
          ),
        );
      },
    );
  }

  /// 判断输入值是否正整数
  static bool isInt(String str) {
    RegExp exp = RegExp(r'^[1-9]\d*.?0*$$');
    return exp.hasMatch(str);
  }

  // 验证是否为数字(正整数+正浮点数)
  static bool isNumber(String str) {
    if (str.isNotEmpty) {
      final reg = RegExp(r'^[0-9]*$|[1-9]\d*\.\d*|0\.\d*[1-9]\d*$');
      logger.d('$str 是否数字:${reg.hasMatch(str)}');
      return reg.hasMatch(str);
    } else {
      return false;
    }
  }

  /// 判断输入值是否正数
  static bool isPositiveNumber(String str) {
    RegExp exp = RegExp(r'^(0|[1-9][0-9]*)(\.\d+)?$');
    logger.i('is positive number ${exp.hasMatch(str)}');
    return exp.hasMatch(str);
  }

  /// 补全前导零
  static String completion(String str, int length) {
    String temp = str;
    while (temp.length < length) {
      temp = '0$temp';
    }
    return temp;
  }

  /// 去掉前导零
  static String removeZero(String str) {
    String temp = str;
    temp = temp.replaceAll(RegExp(r'^(0+)'), '');
    return temp;
  }

  /// map按Key值排序
  static List mapSortByKey(Map map) {
    List keys = map.keys.toList();
    // key排序
    keys.sort((a, b) {
      return a.compareTo(b);
    });
    return keys;
  }

  /// 检查交货单是否符合要求
  static bool checkVO(String vo, bool isIn) {
    RegExp reIn = RegExp(r'^(1)\d*');
    RegExp reOut = RegExp(r'^(8)\d*');
    RegExp reOut2 = RegExp(r'^(6)\d*');
    if (isIn) {
      return reIn.hasMatch(vo);
    } else {
      return reOut.hasMatch(vo) || reOut2.hasMatch(vo);
    }
  }

  /// 处理扫描条码
  static String huHandle(String huNo) {
    if (huNo.isNotEmpty) {
      List huList = huNo.split(',');
      return huList[0];
    } else {
      return '';
    }
  }

  /// 检查条码是否SRM条码
  static bool checkSRM(String hu) {
    RegExp reSRM = RegExp(r'^(1|3)\d*');
    return reSRM.hasMatch(hu);
  }

  /// 检查条码是否符合旧条码规范
  static bool checkBarcode(String hu) {
    RegExp reOld = RegExp(r'^(QR:)\d*');
    return reOld.hasMatch(hu);
  }

  /// 通过周数和星期计算日期
  /// year 年
  /// week 周
  /// day  星期(0-6,   0代表周日)
  static String dateFromWeek(int year, int week, int day) {
    var firstDay = DateTime(year);
    var currentDay = firstDay
        .add(Duration(days: (7 * (week - 1) + day - (firstDay.weekday - 1))));
    return currentDay.year.toString() +
        ((10 <= currentDay.month)
            ? currentDay.month.toString()
            : '0${currentDay.month}') +
        ((10 <= currentDay.day)
            ? currentDay.day.toString()
            : '0${currentDay.day}');
  }

  /// 检查字符串是否符合MAC地址规范
  static bool checkMAC(String mac) {
    RegExp reMAC = RegExp(r'[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}');
    return reMAC.hasMatch(mac);
  }

  /// 检查字符串是否是浮点数
  static bool checkNum(String strNum) {
    RegExp regFloat = RegExp(r'^\d+(\.\d+)?$');
    return regFloat.hasMatch(strNum);
  }

  ///判断是否为大写字母
  static bool isUpperCase(String string) {
    if (string.isEmpty) {
      return false;
    }
    if (string.trimLeft().isEmpty) {
      return false;
    }
    String firstLetter = string.trimLeft();
    if (double.tryParse(firstLetter) != null) {
      return false;
    }
    return firstLetter.toUpperCase() == string;
  }

  /// 数值显示格式化
  static String valueFormate(String value) {
    if (checkNum(value)) {
      if (isInt(value) || '0' == value) {
        return Decimal.parse(value).toBigInt().toString();
      } else {
        return Decimal.parse(value).toDouble().toString();
      }
    } else {
      return '';
    }
  }

  /// 用DecimalFormat来格式化double结果，这样转换成字符串就不会采用科学计数法。
  /// @param d
  /// @return
  static String double2Str(double d) {
    NumberFormat formatter = NumberFormat('#####.####');
    return formatter.format(d);
  }


}
